package cn.carlos.jiatu.api.impl;
import cn.carlos.jiatu.protocol.dto.BookDTO;
import cn.carlos.jiatu.protocol.dto.LibInfoDTO;
import cn.carlos.jiatu.protocol.dto.Payload;
import cn.carlos.jiatu.protocol.dto.RequestDTO;
import cn.carlos.jiatu.protocol.vo.BookInfoVO;
import cn.carlos.jiatu.protocol.vo.HoldingVO;
import cn.carlos.jiatu.api.IJiatuLibService;
import cn.carlos.jiatu.protocol.vo.ResultVO;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;
import com.mashape.unirest.http.exceptions.UnirestException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;


import java.io.*;
import java.net.*;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName JiatuLibServeice
 * @Description TODO
 * @Author Carlos
 * @Date 2023/11/2 12:01
 * @Version 1.0
 */
@Service
@Slf4j
public class JiatuLibServeice implements IJiatuLibService {

    @Value("${jiatu.config.privateKey}")
    private String privateKey;
    @Value("${jiatu.config.appid}")
    private String appid;
    @Value("${jiatu.config.libcode}")
    private String libcode;



    @Override
    public ResultVO createOrder(Payload payload) {

        log.info("payload:{}",payload);
        long time = System.currentTimeMillis();
        String api = "apiGatewayBookOrderService.borrowImidiately";
        RequestDTO requestDTO = new RequestDTO(api,time,payload);
        requestDTO.setAppid(appid);
        requestDTO.setLibcode(libcode);
        String sign = requestDTO.getAppid()+api+requestDTO.getLibcode()+time+privateKey;
        log.info("sign:{}",sign);
        sign = getMD5(sign);
        requestDTO.setSign(sign);
        log.info("requestDTO:{}",requestDTO);
        String url = "https://lib1.jieshu.me/cloudils/api/gateway/dispatch";
        JSONObject obj = (JSONObject) JSON.toJSON(requestDTO);
        log.info("jsonobj:{}",obj);
        String param = obj.toString();
        log.info("jsonparam:{}",param);

        try{
            URL url1 = new URL(url);
            HttpURLConnection conn = (HttpURLConnection) url1.openConnection();
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Content-Type", "application/json");
            conn.setDoOutput(true);
            DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
            wr.writeBytes(param);
            wr.flush();
            wr.close();
            int statusCode = conn.getResponseCode();
            log.info("statusCode:{}",statusCode);
            BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String responseBody = "";
            StringBuilder response = new StringBuilder();
            while ((responseBody = in.readLine()) != null) {
                response.append(responseBody);
            }
            log.info("response:{}",response);
            in.close();
            return JSON.parseObject(response.toString(),ResultVO.class);
        } catch (ProtocolException e) {
            return new ResultVO(4001,e.getMessage());
        } catch (MalformedURLException e) {
            return new ResultVO(4002,e.getMessage());
        } catch (IOException e) {
            return new ResultVO(4003,e.getMessage());
        }
    }

    @Override
    public BookInfoVO findBooK(BookDTO bookDTO) {
        log.info("param:{}",bookDTO);
        String apiUrl = "http://reader.szlib.com/opac/search?";
        // 构建请求参数
        Map<String, String> parameters = new HashMap<>();
        parameters.put("searchWay0", bookDTO.getSearchWay0());
        parameters.put("logical0",bookDTO.getLogical0());
        parameters.put("searchWay1",bookDTO.getSearchWay1());
        parameters.put("logical1",bookDTO.getLogical1());
        parameters.put("searchWay2",bookDTO.getSearchWay2());
        parameters.put("sortWay",bookDTO.getSortWay());
        parameters.put("sortOrder",bookDTO.getSortOrder());
        parameters.put("startPubdate",bookDTO.getStartPubdate());
        parameters.put("endPubdate",bookDTO.getEndPubdate());
        parameters.put("rows",bookDTO.getRows()+"");
        parameters.put("hashholding",bookDTO.getHasholding()+"");
        parameters.put("view","json");
        parameters.put("return_fmt","json");
        if(bookDTO.getQ0() != null && bookDTO.getQ0() != ""){
            parameters.put("q0",URLEncoder.encode(bookDTO.getQ0()));
        }
        if(bookDTO.getQ1() != null && bookDTO.getQ1() != ""){
            parameters.put("q1",URLEncoder.encode(bookDTO.getQ0()));
        }
        if(bookDTO.getQ2() != null && bookDTO.getQ2() != ""){
            parameters.put("q2",URLEncoder.encode(bookDTO.getQ0()));
        }
        for (Map.Entry<String, String> entry : parameters.entrySet()) {
            if(entry.getValue() == null ){
                entry.setValue("");
            }
        }
        log.info("parameters:{}",parameters);

        StringBuilder urlBuilder = new StringBuilder(apiUrl);
        log.info("urlBuilder:{}",urlBuilder);

        for (Map.Entry<String, String> entry : parameters.entrySet()) {
            urlBuilder.append(entry.getKey()).append("=")
                    .append(entry.getValue()).append("&");
        }
        urlBuilder.deleteCharAt(urlBuilder.length()-1);
        log.info("urlBuilder:{}",urlBuilder);
        try {
            HttpResponse<String> response = Unirest.get(urlBuilder.toString())
                    .header("User-Agent", "Apifox/1.0.0 (https://apifox.com)")
                    .header("Accept", "*/*")
                    .header("Host", "reader.szlib.com")
                    .header("Connection", "keep-alive")
                    .asString();
            return JSON.parseObject(response.getBody(),BookInfoVO.class);
        } catch (UnirestException e) {
            return new BookInfoVO();
        }
    }

    @Override
    public HoldingVO libInfo(LibInfoDTO libInfoDTO) {
        log.info("libInfoDTO:{}", libInfoDTO);
        String url1 = "";
        if (libInfoDTO.getLimitLibcodes() == null) {
            url1 = "http://reader.szlib.com/opac/api/holding/" + libInfoDTO.getBookRecord()
                    + "?limitLibcodes=&isCluster=" + libInfoDTO.getIsCluster();
        } else {
            url1 = "http://reader.szlib.com/opac/api/holding/" + libInfoDTO.getBookRecord()
                    + "?limitLibcodes=" + libInfoDTO.getLimitLibcodes() + "&isCluster=" + libInfoDTO.getIsCluster();
        }

        log.info("url1:{}", url1);
        try {
            HttpResponse<String> response = Unirest.get(url1)
                    .header("User-Agent", "Apifox/1.0.0 (https://apifox.com)")
                    .header("Accept", "*/*")
                    .header("Host", "reader.szlib.com")
                    .header("Connection", "keep-alive")
                    .asString();
            return JSON.parseObject(response.getBody(),HoldingVO.class);
        } catch (UnirestException e) {
            return new HoldingVO();
        }
    }


        //MD5加密方法
    private static String getMD5(String message) {
        String md5str = "";
        log.info("message:{}",message);
        try {
            // 创建一个 MessageDigest 实例:
            MessageDigest md = MessageDigest.getInstance("MD5");
            // 将字符串转换为字节流，然后进行 MD5 散列计算:
            byte[] input = message.getBytes();
            byte[] buff = md.digest(input);

            // 将 MD5 计算结果表示成字符串:
            md5str = bytesToHex(buff);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        log.info("md5str:{}",md5str);
        return md5str;
    }

    // 将 byte 数组转换为表示16进制值的字符串
    private static String bytesToHex(byte[] bytes) {
        StringBuilder hexStr = new StringBuilder();
        for (byte b : bytes) {
            int num = b & 0xff;
            String hex = Integer.toHexString(num);
            if (hex.length() < 2) {
                hexStr.append("0");
            }
            hexStr.append(hex);
        }
        return hexStr.toString();
    }

}
